﻿using System;
using System.Windows.Forms;
using System.Security;
using System.Text;
using System.Linq;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;
using System.Management;
using System.Security.Principal;
using System.Security.Cryptography;
using System.IO;

namespace PowerTriggers
{
    public static class Program
    {
        //        delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);

        //        [DllImport("USER32.DLL")]
        //        static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);

        //        [DllImport("USER32.DLL")]
        //        static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        //        [DllImport("USER32.DLL")]
        //        static extern int GetWindowTextLength(IntPtr hWnd);

        //        [DllImport("USER32.DLL")]
        //        static extern bool IsWindowVisible(IntPtr hWnd);

        //        [DllImport("USER32.DLL")]
        //        static extern IntPtr GetShellWindow();

        //        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        //        static extern Int32 SetForegroundWindow(IntPtr hwnd);

        //        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        //        static extern Int32 SetActiveWindow(IntPtr hwnd);



        //        [DllImport("user32.dll", SetLastError = true)]
        //        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        //        // When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
        //        [DllImport("user32.dll")]
        //        static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

        ////        [DllImport("kernel32.dll", SetLastError = true)]
        ////        static extern int GetProcessId(IntPtr hWnd); 



        //        //[DllImport("user32.dll")]
        //        //internal static extern int SendMessage(
        //        //      int hWnd,      // handle to destination window
        //        //      uint Msg,       // message
        //        //      long wParam,  // first message parameter
        //        //      long lParam   // second message parameter
        //        //      );

        [DllImport("User32.DLL")]
        private static extern int SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);

        //        [DllImport("User32")]
        //        private static extern int ShowWindow(IntPtr hwnd, Int32 nCmdShow);

        //        private const Int32 WM_SYSCOMMAND = 0x112;
        //        private const Int32 SC_RESTORE = 0xF120;
        //        private const Int32 SC_MINIMIZE = 0xF020;
        //        private const Int32 SW_HIDE = 0;
        //        private const Int32 SW_SHOWNORMAL       = 1;
        //        private const Int32 SW_NORMAL           = 1;
        //        private const Int32 SW_SHOWMINIMIZED    = 2;
        //        private const Int32 SW_SHOWMAXIMIZED    = 3;
        //        private const Int32 SW_MAXIMIZE         = 3;
        //        private const Int32 SW_SHOWNOACTIVATE   = 4;
        //        private const Int32 SW_SHOW             = 5;
        //        private const Int32 SW_MINIMIZE         = 6;
        //        private const Int32 SW_SHOWMINNOACTIVE  = 7;
        //        private const Int32 SW_SHOWNA           = 8;
        //        private const Int32 SW_RESTORE          = 9;
        //        private const Int32 SW_SHOWDEFAULT      = 10;
        //        private const Int32 SW_FORCEMINIMIZE    = 11;
        //        private const Int32 SW_MAX              = 11;

        private const uint BCM_SETSHIELD = 0x0000160C;

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope"), STAThread]
        private static void Main(string[] args)
        {
            //var windows = GetOpenWindows();
            bool okToContinue = true;
            Process thisProcess = Process.GetCurrentProcess();
            string currentOwner = GetProcessOwner(thisProcess.Id).ToLower();
            if (currentOwner != null)
            {
#if DEBUG
                List<Process> sameProcesses = new List<Process>();
#else
                List<Process> sameProcesses = Process.GetProcessesByName(thisProcess.ProcessName).ToList();
#endif
                List<Process> otherProcesses = sameProcesses
                                    .Where(p => p.Id != thisProcess.Id)
                                    .Where(p => GetProcessOwner(p.Id) != null)
                                    .Where(p => GetProcessOwner(p.Id).ToLower() == currentOwner)
                                    .Where(p => !p.HasExited)
                                    .ToList();

                foreach (Process process in otherProcesses.ToList())
                {
                    if (process.MainWindowHandle == IntPtr.Zero // if it's minimized to system tray
                        || !process.Responding) // or if it is dead
                    {
                        if (!process.HasExited)
                        {
                            process.Kill();
                            otherProcesses.Remove(process);
                        }
                    }
                }

                foreach (Process process in otherProcesses.ToList())
                {
                    if (!process.HasExited)
                    {
                        if (process.MainWindowHandle != IntPtr.Zero) // not hidden
                        {
                            try
                            {
                                Microsoft.VisualBasic.Interaction.AppActivate(process.Id);
                                okToContinue = false; // successfully activated at least one process so do not continue with launching this one
                            }
                            catch { }
                        }
                    }
                }

                foreach (var process in sameProcesses)
                {
                    process.Dispose();
                }
            }
            thisProcess.Dispose();

            if (okToContinue)
            {
                Application.EnableVisualStyles();
                ProgramContext context = new ProgramContext(args);
                Application.Run(context);
            }
        }

        private static string GetProcessOwner(int processId)
        {
            string query = "Select * From Win32_Process Where ProcessID = " + processId;
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            ManagementObjectCollection processList = searcher.Get();

            foreach (ManagementObject obj in processList)
            {
                string[] argList = new string[] { string.Empty };
                int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
                if (returnVal == 0)
                {
                    return argList[0];
                }
            }

            return null;
        }

        private static byte[] bytes = ASCIIEncoding.ASCII.GetBytes("FredCool");

        internal static string EncryptString(string originalString)
        {
            if (String.IsNullOrEmpty(originalString))
            {
                throw new ArgumentNullException
                       ("The string which needs to be encrypted can not be null.");
            }
            string encrpted;
            DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoProvider.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write))
                {
                    using (StreamWriter writer = new StreamWriter(cryptoStream))
                    {
                        writer.Write(originalString);
                        writer.Flush();
                        cryptoStream.FlushFinalBlock();
                        writer.Flush();
                        encrpted = Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
                    }
                }
            }

            return encrpted;
        }

        internal static string DecryptString(string cryptedString)
        {
            if (String.IsNullOrEmpty(cryptedString))
            {
                throw new ArgumentNullException
                   ("The string which needs to be decrypted can not be null.");
            }
            DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
            string decrypted;
            using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(cryptedString)))
            {
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoProvider.CreateDecryptor(bytes, bytes), CryptoStreamMode.Read))
                {
                    using (StreamReader reader = new StreamReader(cryptoStream))
                    {
                        decrypted = reader.ReadToEnd();
                    }
                }
            }

            return decrypted;
        }

        internal static bool IsCurrentUserAdministrator
        {
            get
            {
                //    WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
                //    return pricipal.IsInRole(WindowsBuiltInRole.Administrator);

                //return false;

                return true;
            }
        }

        //internal static bool SetControlUAC(Button control)
        //{
        //    if (!IsCurrentUserAdministrator)
        //    {
        //        control.FlatStyle = FlatStyle.System;
        //        SendMessage(control.Handle, BCM_SETSHIELD, 0, 1);
        //        return true;
        //    }
        //    else
        //    {
        //        return false;
        //    }
        //}
    }
}

